package controller

import (
	"encoding/json"
	"github.com/astaxie/beego"
	"github.com/qiniu/log"
	"mars/nearby/data"
)

var actionMap map[string]Action

func init() {
	RegisterAction(&addHotspot{"ADDHOTSPOT"}, &nearbyAction{"NEARBYHOTSPOT"})
}
func RegisterAction(as ...Action) {
	if actionMap == nil {
		actionMap = make(map[string]Action)
	}
	for _, v := range as {
		actionMap[v.Command()] = v
	}
}

type ClientAction struct {
	beego.Controller
}

func (ca *ClientAction) Post() {
	command := ca.Ctx.Input.Param(":action")
	action, ok := actionMap[command]
	if !ok {
		log.Warnf("Unknow Command %s", command)
		ca.Data["json"] = NewResult(false, "Unknow command")
		ca.ServeJson()
		return
	}
	data := ca.GetString("data")
	log.Warn(data)
	order, err := action.OnParse([]byte(data))
	if err != nil {
		log.Warn(err.Error())
		ca.Data["json"] = NewResult(false, err.Error())
	} else {
		ca.Data["json"] = action.HandleMessage(order)
	}
	ca.ServeJson()
}

type Order struct {
	Command string      `json:"command"`
	Data    interface{} `json:"data"`
}
type Result struct {
	State   bool        `json:"state"`
	Message string      `json:"message"`
	Data    interface{} `json:"data"`
}

func NewResult(state bool, message string) *Result {
	return &Result{State: state, Message: message}
}

type Action interface {
	Command() string
	OnParse(data []byte) (*Order, error)
	HandleMessage(order *Order) *Result
}

//add hotspot
type addHotspot struct {
	order string
}

func (this *addHotspot) Command() string {
	return this.order
}
func (this *addHotspot) OnParse(bits []byte) (*Order, error) {
	order := &Order{Data: &data.Hotspot{}}
	err := json.Unmarshal(bits, order)
	return order, err
}
func (this *addHotspot) HandleMessage(order *Order) *Result {
	hotspot, ok := order.Data.(*data.Hotspot)
	if !ok {
		return NewResult(false, "Error data type")
	}
	result := NewResult(false, "Failed to add hotspot")
	spotdao := &data.HotspotAccess{}
	state, err := spotdao.Add(hotspot)
	if state && err == nil {
		result.State, result.Message = true, "Success"
	}
	return result
}

//nearby
type nearbyAction struct {
	order string
}

func (this *nearbyAction) Command() string {
	return this.order
}
func (this *nearbyAction) OnParse(bits []byte) (*Order, error) {
	order := &Order{Data: &data.Circle{}}
	err := json.Unmarshal(bits, order)
	log.Print(order.Data)
	return order, err
}
func (this *nearbyAction) HandleMessage(order *Order) *Result {
	circle, ok := order.Data.(*data.Circle)
	if !ok {
		return NewResult(false, "Error Data Type")
	}
	spotdao := &data.HotspotAccess{}
	data, err := spotdao.NearBy(circle)
	if err != nil {
		return NewResult(false, err.Error())
	}
	return &Result{State: true, Message: "Success", Data: data}
}
